#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 1024 

#define NONE_REDIRECT -1
#define INPUT_REDIRECT 0
#define OUTPUT_REDIRECT 1
#define APPEND_REDIRECT 2

int redirect_flag = NONE_REDIRECT;
char* redirect_filename = NULL;

void get_command(char* command)
{
    printf("[%s@ali %s]$ " , getenv("USER"), getenv("PWD"));
    gets(command);
}
void split_command(char** argv, char* command)
{
    //处理重定向命令
    redirect_flag = NONE_REDIRECT;  //先进行初始化
    redirect_filename = NULL;

    int n = strlen(command) - 1;
    while(n >= 0)
    {
        if(command[n] == '>')
        {
            if(n - 1 && command[n - 1] == '>')
            {
                redirect_flag = APPEND_REDIRECT;
                command[n - 1] = 0;
                n++;
                while(command[n] == ' ') n++;
                redirect_filename = command + n;
                break;
            }
            redirect_flag = OUTPUT_REDIRECT;
            command[n++] = 0;
            while(command[n] == ' ') n++;
            redirect_filename = command + n;
            break;
        }
        else if(command[n] == '<')
        {
            redirect_flag = INPUT_REDIRECT;
            command[n++] = 0;
            while(command[n] == ' ') n++;
            redirect_filename = command + n;
            break;
        }
        n--;
    }   //处理完成

    int i = 0;
    argv[i++] = strtok(command, " ");
    while(argv[i++] = strtok(NULL, " ")) ;

    if(strcmp(argv[0], "ll") == 0)
    {
        argv[0] = "ls"; 
        argv[i - 1] = "-al";
        argv[i] = NULL;
    }
}
int open_dir()
{
    int fd = -1;
    if(redirect_flag == INPUT_REDIRECT)
    {
        fd = open(redirect_filename, O_RDONLY);
        dup2(fd, 0);
    }
    else if(redirect_flag == OUTPUT_REDIRECT)
    {
        fd = open(redirect_filename, O_CREAT | O_WRONLY | O_TRUNC);
        dup2(fd, 1);
    }
    else if(redirect_flag == APPEND_REDIRECT)
    {
        fd = open(redirect_filename, O_CREAT | O_WRONLY | O_APPEND);
        dup2(fd, 1);
    }
}
void sub_process(char** argv)
{
    int id = fork();
    if(id == 0)
    {
        open_dir(); //处理是否要打开文件
        int ret = execvp(argv[0], argv);
        if(ret = -1)
        {
            perror("command error");
            exit(1);
        }
    }
    //父进程等待
    waitpid(id, NULL, 0);
}

/// @brief 
/// @param argv 
/// @return 判断是否为内建命令，是返回1，否返回0 
int build_incmd(char** argv)
{
    if(strcmp(argv[0], "cd") == 0)
    {
        if(argv[1]) chdir(argv[1]);
        else chdir(getenv("HOME"));
        char path[512], out[512];
	    getcwd(path,sizeof(path));
        sprintf(out, "PWD=%s", path);
        putenv(out);
        return 1;
    }

    return 0;
}
int main()
{
    char command[SIZE];
    while(1)
    {
        char* exec_argv[SIZE];
        
        get_command(command);   //打印输出内容并获取命令
        
        split_command(exec_argv, command);      //将命令进行分割
        
        int flag = build_incmd(exec_argv);     //处理内建命令
        
        if(flag == 0)
            sub_process(exec_argv);     //进程替换
    }
    return 0;
}